<template>
    <div>
        <van-uploader
            v-model="uploadObj.fileList"
            :after-read="afterRead"
            :before-read="beforeRead"
            :disabled='uploadObj.uploadDisabled'
            :max-count="uploadObj.uploadCount"
            :max-size="uploadObj.uploadSize * 1024"
            :before-delete="beforeDel"
            @oversize="onOversize"
            @delete="handleDel"
            :upload-icon='uploadObj.photoType'
            v-if="uploadObj.photoType!='photo'"
            multiple>
        </van-uploader>
        <van-uploader
            v-model="fileList"
            :after-read="afterRead"
            :before-read="beforeRead"
            :disabled='uploadObj.uploadDisabled'
            :max-count="uploadObj.uploadCount"
            :max-size="uploadObj.uploadSize * 1024"
            :before-delete="beforeDel"
            @oversize="onOversize"
            @delete="handleDel"
            v-else
            multiple>
            <div class="upload_box">
               <van-icon name="photo" color="#1989fa" size="0.5rem" />
               <span class="txt">上传图片</span>
            </div>
        </van-uploader>
    </div>
</template>
<script>
import { onMounted, reactive, toRefs, watch } from 'vue'
import { Toast, Dialog } from 'vant'
import { uploadfile } from '@/utils/getData.js'
export default {
    props: {
        modelValue: { // v-model 绑定的值
            type: [Array, String]
        },
        isDisabled: { // 是否禁用
            type: Boolean,
            default: false
        },
        maxCount: { // 上传数量
            type: [Number, String],
            default: 20
        },
        maxSize: { // 文件大小
            type: Number,
            default: Number.MAX_VALUE
        },
        fileType: { // 文件类型  选值：image(图片模式)  默认：全部
            type: String,
            default: 'ALL'
        },
        cssType: { // 组件样式 默认：photograph 可选值：plus（十字） photo
            type: String,
            default: 'photograph'
        },
        sendType: { // 发送的数据格式 默认：array 可选值： str（字符串）
            type: String,
            default: 'array'
        }
    },
    components: {
        [Dialog.Component.name]: Dialog.Component
    },
    setup (props, { emit }) {
        // 解构传参属性
        const { isDisabled, maxCount, maxSize, fileType, cssType, modelValue, sendType } = toRefs(props)
        // 自身的属性
        const uploadObj = reactive({
            uploadDisabled: isDisabled.value, // 是否禁用
            uploadCount: maxCount.value, // 上传数量
            uploadSize: maxSize.value, // 上传大小 单位为 byte
            photoType: cssType.value, // 上传样式
            fileList: modelValue.value, // 预览列表
            backList: modelValue.value // 返回数据列表
        })
        onMounted(() => {
            if (sendType.value === 'str') {
                const changeArr = [];
                uploadObj.backList.forEach((item) => {
                    changeArr.push(item.file_id);
                });
                emit('update:modelValue', changeArr.toString());
            }
        });
        // 监听函数
        watch([uploadObj.backList], ([val]) => {
            if (sendType.value === 'str') {
                const changeArr = [];
                val.forEach((item) => {
                    changeArr.push(item.file_id);
                });
                emit('update:modelValue', changeArr.toString());
            } else {
                emit('update:modelValue', val);
            }
        });
        // 上传前置处理
        const beforeRead = (file) => {
            if (file.type !== 'image/jpeg' && file.type !== 'image/png' && fileType.value === 'image') {
                Toast('请上传图片文件');
                return false
            }
            return true
        }
        const compressHandle = (file) => { // 图片压缩
            try {
                return new Promise((resolve, reject) => {
                    if (file.file.size > 200 * 1024) { // 小于200kb则不压缩
                        let fileContent = '';
                        // 创建Canvas对象(画布)
                        const canvas = document.createElement('canvas');
                        // 获取对应的CanvasRenderingContext2D对象(画笔)
                        const context = canvas.getContext('2d');
                        // 创建新的图片对象
                        const img = new Image();
                        // 指定图片的DataURL(图片的base64编码数据)
                        img.src = file.content;
                        // 监听浏览器加载图片完成，然后进行进行绘制
                        img.onload = () => {
                            // 指定canvas画布大小，该大小为最后生成图片的大小
                            canvas.width = img.width;
                            canvas.height = img.height;
                            /* drawImage画布绘制的方法。(0,0)表示以Canvas画布左上角为起点，400，300是将图片按给定的像素进行缩小。
                            如果不指定缩小的像素图片将以图片原始大小进行绘制，图片像素如果大于画布将会从左上角开始按画布大小部分绘制图片，最后的图片就是张局部图。 */
                            context.drawImage(img, 0, 0, img.width, img.height);
                            // 将绘制完成的图片重新转化为base64编码，file.file.type为图片类型，0.92为默认压缩质量
                            fileContent = canvas.toDataURL(file.file.type, 0.92);
                            resolve(fileContent);
                        };
                        // img.onerror = ()=>{
                        //     reject();
                        // }
                    } else {
                        resolve(file.content);
                    }
                });
            } catch (e) {
                Toast(e.message);
            }
        }
        // 上传后的回调函数
        const afterRead = async (file) => {
            const item = await compressHandle(file); // 图片压缩
            file.status = 'uploading';
            file.message = '上传中...';
            const res = await uploadfile({ base64: item, showLoad: 1 });
            if (res.code === '200') {
                file.status = 'done';
                uploadObj.backList.push(res.data[0]); // 将返回的数据存入
                uploadObj.fileList = uploadObj.backList; // 将添加的数据赋值给预览列表
            } else {
                file.status = 'failed';
                file.message = '上传失败';
            }
        }
        // 文件大小超过限制的回调
        const onOversize = (file) => {
            Toast(`文件大小不能超过 ${uploadObj.uploadSize}kb`)
        }
        // 文件删除前的回调
        const beforeDel = async (file) => {
            let flag = false;
            await Dialog.confirm({
                title: '提示',
                message: '确认是否删除？'
            })
            .then(() => {
                flag = true;
            })
            .catch(() => {
                flag = false;
            });
            return flag;
        }
        // 文件删除回调
        const handleDel = (file) => {
            const index = uploadObj.backList.findIndex((item) => {
                return item.file_id === file.file_id
            })
            if (index !== -1) {
                uploadObj.backList.splice(index, 1);
            }
        }
        return {
            uploadObj,
            beforeRead,
            afterRead,
            onOversize,
            beforeDel,
            handleDel
        }
    }
}
</script>
<style lang="scss" scoped>
    .upload_box{
        background: #f6f8fa;
        border-radius: 46px;
        width: 200px;
        text-align: center;
        font-size: 12px;
        display: flex;
        flex-direction: row;
        align-items: flex-end;
        justify-content: center;
        padding: 2px 0;
        .txt{
            padding-left: 5px;
            padding-bottom: 2px;
        }
    }
</style>